class Node {
    constructor(name = "_"){
        this._make_id(name);

        this.PCs = {
            'offer_pcs':{
                '_':this._make_pc(proactive = true),
            },
            'answer_pcs':{},
            'connected_pcs':{},
        }
    }

    _make_id = (name) => {
        // 生成随机id
        this.id = name + "-" + Math.random().toString(36).substr(2);
    };

    _make_pc = (remote_id,proactive = true) => {
        const config = {
            iceServers: [{ urls: "stun:stun.ideasip.com" }]
        }
        const pc = new RTCPeerConnection(config);
        pc.remote_id = remote_id;
        pc.proactive = proactive;
        pc.temp_candidates = [];
        pc.candidates = [];

        if (pc.proactive){
            pc.onnegotiationneeded = async (e) => {
                const offer = await e.target.createOffer()
                await e.target.setLocalDescription(offer);
                /*
                    此处更新key
                */
                log("key 更新点(offer_obj.pc.createOffer)");
                this._update_key(e.target);
            //    this._send_keys();
            };

            pc.addEventListener('connectionstatechange',(e) => {
                switch (e.target.connectionState) {
                    case 'connected':
                        this.PCs.connected_pcs[e.target.remote_id] = e.target;
                        this.PCs.offer_pcs[e.target.remote_id] = null;
                        /*
                            此处更新key
                        */
                       this._update_key(e.target);
                        break;
                }
            });
        } else {

            pc.addEventListener('connectionstatechange',(e) => {
                switch (e.target.connectionState) {
                    case 'connected':
                        this.PCs.connected_pcs[e.target.remote_id] = e.target;
                        this.PCs.answer_pcs[e.target.remote_id] = null;
                        /*
                            此处更新key
                        */
                        this._update_key(e.target);
                        break;
                }
            });
        }


        pc.onicecandidate = ({ candidate }) => {
            if (candidate) {
                e.target.temp_candidates.push(candidate)
            } else {
                e.target.candidates = this.offer_obj.temp_candidates;
                e.target.temp_candidates = [];
                /*
                    此处更新key
                */
               log("key 更新点(offer_obj.pc.onicecandidate)");
               this._update_key(e.target);
            }
        }

        pc.addEventListener('connectionstatechange',(e) => {
            switch (e.target.connectionState) {
                case "connecting":
                    break;
                case 'connected':
                    break;
                default:
                    log("收到未知状态:(" + e.target.connectionState + ")")
            }
        });

        return pc;
    };

    _send_one_key = (combined_key) => {

    };

    _clean_keys = () => {

    };
    /* 首先，有小概率情况两个node之间同时互传了offer和answer，因此offer-pc和answer-pc需要同时存在，然后根据连接情况保存其一或其二
    如果不分开存储，当需要关闭特定的remote node的已连接pc时，好像也没啥问题。
    */
    _update_key = (remote_id) => {
        let combined_key = {
            'state':,
            'self_id':this.id,
            'target_id':remote_id,
            'desc':null,
            'candis':[],
        }
        if (remote_id in this.PCs.offer_pcs){
            combined_key.desc = this.PCs.offer_pcs[target_id].localDescription;
            combined_key.candis = this.PCs.offer_pcs[target_id].candidates;
        } else if (remote_id in this.PCs.answer_pcs){

        } else if (remote_id in this.connected_pcs){

        } else {

        }

    };

    _send_keys = () => {
        // 发送自己的key，以进行连接

        this._clean_keys();

        for (target_id in this.PCs.offer_pcs){
            let combined_key = {
                'self_id':this.id,
                'target_id':target_id,
                'desc':this.PCs.offer_pcs[target_id].localDescription,
                'candis':this.PCs.offer_pcs[target_id].candidates,
            };
            if (combined_key.desc !== null && combined_key.candis.length){
                this._send_one_key(combined_key);
            }

        };
        for (target_id in this.PCs.answer_pcs){
            let combined_key = {
                'self_id':this.id,
                'target_id':target_id,
                'desc':this.PCs.answer_pcs[target_id].localDescription,
                'candis':this.PCs.answer_pcs[target_id].candidates,
            };
            if (combined_key.desc !== null && combined_key.candis.length){
                this._send_one_key(combined_key);
            }

        };

    };

    _recive_one_key = (remote_key) => {

        // 接收远程的key，以进行连接
        if (remote_key.target_id !== this.id){
            log(`收到的远程key的目标Node(${remote_key.target_id})不是本Node(${this.id})，舍弃该key...`);
            return;
        }

        if (remote_key.self_id in this.PCs.connected_pcs) {
            log(`与收到的远程key的远程Node(ID:${remote_key.self_id})已经连接了!舍弃该key...`);
            return;
        }

        switch(remote_key.desc.type){
            case "offer":
                if (!remote_key.self_id in this.PCs.answer_pcs){
                    this.PCs.answer_pcs[remote_key.self_id] = this._make_pc(remote_key.self_id,proactive = false);
                }
                await this.PCs.answer_pcs[remote_key.self_id].setRemoteDescription(remote_key.desc);
                const answer = await this.PCs.answer_pcs[remote_key.self_id].createAnswer()
                await this.PCs.answer_pcs[remote_key.self_id].setLocalDescription(answer);
                log(`(${this.id} <==> ${remote_key.self_id})[answer_pc]offer description已处理，answer description已生成，请回复`);
                /*
                    此处更新key
                */
                log("key 更新点(answer_pc.createAnswer)");
                this._update_key(this.PCs.answer_pcs[remote_key.self_id]);
                // this._send_keys();

                for (const i in remote_key.candis) {

                    if (remote_key.candis[i]) {
                        await this.PCs.answer_pcs[remote_key.self_id].addIceCandidate(remote_key.candis[i]);
                    };
                };
                log(`(${this.id} <==> ${remote_key.self_id})[answer_pc]远程candidates已加入`);
                break;
            case "answer":
                if (!remote_key.self_id in this.PCs.offer_pcs){
                    this.PCs.offer_pcs[remote_key.self_id] = this.PCs.offer_pcs['_'];
                    this.PCs.offer_pcs[remote_key.self_id].remote_id = remote_key.self_id;
                    this.PCs.offer_pcs['_'] = this._make_pc('_',proactive = true);
                }
                await this.PCs.offer_pcs[remote_key.self_id].setRemoteDescription(remote_key.desc);
                log(`(${this.id} <==> ${remote_key.self_id})[offer_pc]answer description已处理`);

                for (const i in remote_key.candis) {

                    if (remote_key.candis[i]) {
                        await this.PCs.offer_pcs[remote_key.self_id].addIceCandidate(remote_key.candis[i]);
                    };
                };
                log(`(${this.id} <==> ${remote_key.self_id})[offer_pc]远程candidates已加入`);
                break;
        }

    };

    close = () => {
        // 断开所有连接，关闭自己
        for (pc_type in this.PCs){
            for (let remote_id in this.PCs[pc_type]){
                this.PCs[pc_type][remote_id].close();
                this.PCs[pc_type][remote_id] = null;
            }
            this.PCs[pc_type] = {};
        };

        this._clean_keys();

    };


}


class DataNode extends Node {
    constructor(name = "_"){
        super(name);
        this._make_pc_channel(this.PCs.offer_pcs._);
        this._make_pc = (remote_id,proactive = true) => {
            return this._make_pc_channel(super._make_pc(remote_id,proactive));
        }
    }

    _make_pc_channel = (pc) => {
        if (pc.proactive) {
            pc.Channel = pc.createDataChannel("Channel");
            pc.Channel.onmessage = this.onMessage;
            pc.Channel.onopen = this.onopen;
            pc.Channel.onclose = this.onclose;
        }
        else {
            pc.ondatachannel = (event) => {
                event.target.Channel = event.channel;
                event.target.Channel.onmessage = this.onMessage;
                event.target.Channel.onopen = this.onopen;
                event.target.Channel.onclose = this.onclose;
            };
        }
    };

    onMessage = (e) => {};
    onopen = (e) => {};
    onclose = (e) => {};

    sendData = (data,target_id = '_') => {
        combined_data = {
            'self_id':this.id,
            'target_id':target_id,
            'content':data
        }
        if (target_id == '_'){
            for (let remote_id in this.PCs.connected_pcs) {
                this.PCs.connected_pcs[remote_id].Channel.send(JSON.stringify(combined_data));
            };
        } else if (target_id in this.PCs.connected_pcs) {
            this.PCs.connected_pcs[target_id].Channel.send(JSON.stringify(combined_data));
        } else {
            log(`发送目标：${target_id} 不存在!`);
        }
    };

    close(){
        for (pc_type in this.PCs){
            for (let remote_id in this.PCs[pc_type]){
                this.PCs[pc_type][remote_id].Channel.close();
                this.PCs[pc_type][remote_id].Channel = null;
            }
        }
        super.close();
    }
}

